#include<linux/kernel.h>
#include<linux/module.h>
#include<linux/platform_device.h>
#include<asm/io.h>
#include<linux/miscdevice.h>
#include<linux/fs.h>
#include<asm/uaccess.h>
#define DEBUG()  printk("-- %s : %d : %s --\n",__FILE__,__LINE__,__func__)


//#defnie PWM (* (volatile pwm *)0x139D0000)
typedef struct {
	unsigned int TCFG0;
	unsigned int TCFG1;
	unsigned int TCON;
	unsigned int TCNTB0;
	unsigned int TCMPB0;
	unsigned int TCNTO0;
	unsigned int TCNTB1;
	unsigned int TCMPB1;
	unsigned int TCNTO1;
	unsigned int TCNTB2;
	unsigned int TCMPB2;
	unsigned int TCNTO2;
	unsigned int TCNTB3;
	unsigned int TCMPB3;
	unsigned int TCNTO3;
	unsigned int TCNTB4;
	unsigned int TCNTO4;
	unsigned int TINT_CSTAT;
}pwm;

typedef struct {
	unsigned int CON;
	unsigned int DAT;
	unsigned int PUD;
	unsigned int DRV;
}gpd0;

volatile pwm *PWM;
volatile gpd0 *GPD0;
void beep_on(void)
{
	PWM->TCON = ( PWM->TCON & (~(0xff)) ) | (1 << 0) | (1 << 3);
}
void beep_off(void)
{
	PWM->TCON =  PWM->TCON & (~(1 << 0));
}
ssize_t beep_write(struct file *filp, const char __user *buf, size_t n, loff_t *off)
{
	char a;
	int err;
	DEBUG();
	err = copy_from_user(&a, buf, 1);
	if(err < 0)
	{
		printk("copy_from_user err!\n");
		return err;
	}
	if(a == '1')
		beep_on();
	else if(a == '2')
		beep_off();
	else
		printk("Get a unreg number\n");
	return n;

}	
int beep_open(struct inode *inodp, struct file *filep)
{
	DEBUG();
	return 0;
}
int beep_close (struct inode *inodp, struct file *filp)
{
	DEBUG();
	return 0;
}
struct file_operations beep_ops = {
	.owner = THIS_MODULE,
	.open  = beep_open,
	.write = beep_write,
	.release = beep_close,

};

struct miscdevice mybeep = {
	.minor = MISC_DYNAMIC_MINOR,
	.name  = "hxjbeep",
	.fops  = &beep_ops,

};



static int driver_probe(struct platform_device *dev)
{
	struct resource *res = NULL;
	DEBUG();
	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
	if(res == NULL)
	{
		printk("platform get resource is error\n");
		return -EINVAL;
	}
	printk("res->start = %#x\n", res->start);
	printk("res->end = %#x\n", res->end);
	printk("res->flags = %#lx\n", res->flags);

	PWM = (volatile pwm *)ioremap(res->start,sizeof(pwm)); 

	res = platform_get_resource(dev, IORESOURCE_MEM, 1);
	if(res == NULL)
	{
		printk("platform get resource is error\n");
		return -EINVAL;
	}
	printk("res->start = %#x\n", res->start);
	printk("res->end = %#x\n", res->end);
	printk("res->flags = %#lx\n", res->flags);

	GPD0 = (volatile gpd0 *)ioremap(res->start,sizeof(gpd0));

	GPD0->CON = ( GPD0->CON & (~(0xf)) ) | 0x2;
	GPD0->PUD = GPD0->PUD & (~(0xf)) ;
	PWM->TCFG0 = ( PWM->TCFG0 & (~(0xff)) ) | 0xf9;
	PWM->TCFG1 = ( PWM->TCFG1 & (~(0xf)) ) | 0x2;
	PWM->TCMPB0 = 50;
	PWM->TCNTB0 = 100;
	PWM->TCON = ( PWM->TCON & (~(0xff)) ) | (1 << 0) | (1 << 1);


//	PWM->TCON = ( PWM->TCON & (~(0xff)) ) | (1 << 0) | (1 << 3);
//	beep_on();
//	beep_off();
	misc_register(&mybeep);
	return 0;

}

static int driver_remove(struct platform_device *dev)
{
	misc_deregister(&mybeep);
	PWM->TCON =  PWM->TCON & (~(1 << 0));
	DEBUG();
	return 0;
}

struct of_device_id test_dtb[] = {
	{.compatible = "hxj",},
	{},
};

struct platform_driver test_driver = {
	.probe  = driver_probe,
	.remove = driver_remove,
	.driver = {
		.name = "nothing",
		.of_match_table = test_dtb,
	},
};
static int __init dri_init(void)
{
	DEBUG();
	platform_driver_register(&test_driver);
	return 0;
}
static void __exit dri_exit(void)
{
	platform_driver_unregister(&test_driver);
	DEBUG();
}
MODULE_LICENSE("GPL");
module_init(dri_init);
module_exit(dri_exit);
